package com.project.core.util;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;

/**
 * @author mengxj
 * @date 2022/5/31 12:33
 */
public class AesUtil extends JcaUtil {

    private static final String DEFAULT_KEY = "score";

    /**
     * 加密，将字符串加密后得到加密数组
     * @param content 待加密字符串
     * @param key 密钥
     * @return 加密数组
     */
    private static byte[] encode(String content, String key){
        try {
            KeyGenerator keyGenerator = KeyGenerator.getInstance(AES);
            keyGenerator.init(128, new SecureRandom(key.getBytes()));
            SecretKey secretKey = keyGenerator.generateKey();
            SecretKeySpec keySpec = new SecretKeySpec(secretKey.getEncoded(), AES);
            Cipher cipher = Cipher.getInstance(AES);
            cipher.init(Cipher.ENCRYPT_MODE, keySpec);
            return cipher.doFinal(content.getBytes());
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }

    /**
     * 解密，将加密的字符串数组解密成原数组
     * @param bytes 加密的字符串数组
     * @param key 密钥
     * @return 原数组
     */
    private static byte[] decodeBytes(byte[] bytes, String key){
        try {
            KeyGenerator keyGenerator = KeyGenerator.getInstance(AES);
            keyGenerator.init(128, new SecureRandom(key.getBytes()));
            SecretKey secretKey = keyGenerator.generateKey();
            SecretKeySpec keySpec = new SecretKeySpec(secretKey.getEncoded(), AES);
            Cipher cipher = Cipher.getInstance(AES);
            cipher.init(Cipher.DECRYPT_MODE, keySpec);
            return cipher.doFinal(bytes);
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }

    /**
     * 加密
     * @param content 原文本
     * @param key 密钥
     * @return 加密密文
     */
    public static String encrypt(String content, String key){
        checkParam(content, "ase util encrypt method param content is not empty!");
        checkParam(key, "ase util encrypt method param key is not empty!");
        byte[] secretBytes = encode(content, key);
        return bytesToStr(secretBytes);
    }

    /**
     * 解密
     * @param content 加密密文
     * @param key 密钥
     * @return 原文本
     */
    public static String decrypt(String content, String key){
        checkParam(content, "ase util decrypt method param content is not empty!");
        checkParam(key, "ase util decrypt method param key is not empty!");
        byte[] bytes = strToBytes(content);
        return new String(decodeBytes(bytes, key));
    }

    /**
     * 加密
     * @param content 原文本
     * @return 加密密文
     */
    public static String encrypt(String content){
        try {
            return encrypt(content, DEFAULT_KEY);
        }catch (Exception e){
            return null;
        }
    }


    /**
     * 解密
     * @param content 加密密文
     * @return 原文本
     */
    public static String decrypt(String content){
        try {
            return decrypt(content, DEFAULT_KEY);
        }catch (Exception e){
            return null;
        }
    }
}
